package com.nicefact.mailmonitor.service;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.mail.MailService;
import com.google.appengine.api.mail.MailService.Message;
import com.google.appengine.api.mail.MailServiceFactory;
import com.google.gdata.client.authn.oauth.GoogleOAuthParameters;
import com.google.gdata.client.authn.oauth.OAuthException;
import com.google.gdata.client.authn.oauth.OAuthHmacSha1Signer;
import com.google.gdata.client.authn.oauth.OAuthParameters.OAuthType;
import com.google.gdata.data.Link;
import com.google.gdata.data.appsforyourdomain.AppsForYourDomainException;
import com.google.gdata.data.appsforyourdomain.provisioning.UserEntry;
import com.google.gdata.data.appsforyourdomain.provisioning.UserFeed;
import com.google.gdata.util.ServiceException;
import com.nicefact.mailmonitor.dao.AppUserDao;
import com.nicefact.mailmonitor.entity.AppUser;
import com.nicefact.mailmonitor.util.UserUtil;
import com.nicefact.mailmonitor.vo.AppProperties;
import com.nicefact.mailmonitor.vo.DomainConfig;
import com.nicefact.mailmonitor.vo.GridRequest;

@Service
public class AppUserService {

	@Autowired
	private AppProperties appProperties;

	@Autowired
	AppUserDao appUserDao;

	@Autowired
	DomainConfig domainConfig;

	public AppUser save(AppUser appUser) {
		AppUser obj = null;
		if (!StringUtils.isBlank(appUser.getEmail())) {
			if (StringUtils.isBlank(appUser.getDomainName())) {
				appUser.setDomainName(UserUtil.getDomain(appUser.getEmail()));
			}
			obj = appUserDao.create(appUser);
		}
		return obj;
	}

	public AppUser getUser(String email) {
		return appUserDao.get(email);
	}
	
	public AppUser getUser(String email,String adminEmail) {
		return appUserDao.get(email,adminEmail);
	}

	public AppUser getUser(Key key) {
		return appUserDao.get(AppUser.class, key);
	}

	public List<AppUser> getAllUsers() {
		return appUserDao.getAll();
	}

	public AppUser updateUserTokenSecret(String email, String accessSecret) {
		AppUser appUser = getUser(email);
		if (appUser == null) {
			appUser = new AppUser();
			appUser.setEmail(email);
		}
		appUser.setOauthtokensecret(accessSecret);
		return save(appUser);
	}

	public AppUser updateUserToken(AppUser appUser, String accessToken) {
		appUser.setOauthtoken(accessToken);
		return save(appUser);
	}

	private List<Key> getKeyListFromInt(List<Long> intList) {
		List<Key> keyList = new ArrayList<Key>();
		for (Long id : intList) {
			// TODO Change Object to desired entity
			Key key = KeyFactory.createKey(Object.class.getSimpleName(), id);
			keyList.add(key);
		}
		return keyList;
	}

	private List<Long> getLongFromString(String str) {
		Set<Long> set = new HashSet<Long>();
		Scanner sc = new Scanner(str);
		sc.useDelimiter(",");
		while (sc.hasNextLong()) {
			set.add(sc.nextLong());
		}
		List<Long> idList = new ArrayList<Long>(set);
		return idList;
	}

	public void sendApprovalMailToUser(String senderEMail, String adminEmail,
			String email, String approvalUrl) {
		Message message = new Message();
		message.setTo(email);
		message.setSubject("Your Domain Admin has requested authorization for "
				+ appProperties.getApplicationName());
		String body = "Hello,<br> "
				+ adminEmail
				+ " has requested your approval for "
				+ appProperties.getApplicationName()
				+ ".<br><br> Please visit the link below and grant approval.<br><br>You must be logged in with your "
				+ UserUtil.getDomain(email)
				+ " account. <br><br><b>Please log out of all other accounts first.</b><br><br> And then click on the following link, or copy/paste in your browser : "
				+ approvalUrl + "<br><br> "
				+ "Please ensure that IMAP is enabled under settings on your "
				+ UserUtil.getDomain(email) + " account."
				+ "<br><br> Thanks and regards, <br>Email Statistics Team.";
		message.setHtmlBody(body);
		message.setSender(senderEMail);
		MailService service = MailServiceFactory.getMailService();
		try {
			service.send(message);
			System.out.println("sending mail to " + email);
		} catch (Exception e) {
			System.out.println("sending mail FAILED for " + email
					+ e.getMessage());
			e.printStackTrace();
		}

	}

	public boolean isDomainAdmin(String email) {
		boolean isAdmin = false;
		// List<String> users = new ArrayList<String>();
		com.google.gdata.client.appsforyourdomain.UserService guserService = new com.google.gdata.client.appsforyourdomain.UserService(
				"ykko-test");

		String consumerKey = appProperties.getConsumerKey();
		String consumerSecret = appProperties.getConsumerKeySecret();
		String urlEscopo = "http://apps-apis.google.com/a/feeds/user/#readonly";
		GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
		oauthParameters.setOAuthConsumerKey(consumerKey);
		oauthParameters.setOAuthConsumerSecret(consumerSecret);
		oauthParameters.setOAuthType(OAuthType.TWO_LEGGED_OAUTH);

		oauthParameters.setScope(urlEscopo);

		try {
			guserService.setOAuthCredentials(oauthParameters,
					new OAuthHmacSha1Signer());
			guserService.setReadTimeout(20000);
			guserService.setConnectTimeout(20000);
			final String APPS_FEEDS_URL_BASE = "https://apps-apis.google.com/a/feeds/";
			final String SERVICE_VERSION = "2.0";

			String domainUrlBase = APPS_FEEDS_URL_BASE
					+ UserUtil.getDomain(email) + "/";

			URL retrieveUrl = new URL(domainUrlBase + "user/" + SERVICE_VERSION);
			UserFeed genericFeed = new UserFeed();

			Link nextLink = null;

			do {
				try {
					UserFeed newGenericFeed = guserService.getFeed(retrieveUrl,
							UserFeed.class);

					genericFeed.getEntries()
							.addAll(newGenericFeed.getEntries());
					nextLink = newGenericFeed.getLink(Link.Rel.NEXT,
							Link.Type.ATOM);
					if (nextLink != null) {
						retrieveUrl = new URL(nextLink.getHref());
					}
				} catch (AppsForYourDomainException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (ServiceException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} while (nextLink != null);

			if (genericFeed != null && genericFeed.getEntries() != null
					&& !genericFeed.getEntries().isEmpty()) {
				for (UserEntry genericEntry : genericFeed.getEntries()) {
					// System.out.println(genericEntry.getLogin().getUserName());
					if (genericEntry
							.getLogin()
							.getUserName()
							.equalsIgnoreCase(
									UserUtil.getUserNameFromEmail(email))
							&& genericEntry.getLogin().getAdmin()) {
						isAdmin = true;
						break;
					}
				}
			}
		} catch (OAuthException e) {
			e.printStackTrace();

		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return isAdmin;
	}

	public List<String> getAllDomainUsers(String domain) {
		List<String> domainUsers = new ArrayList<String>();
		// List<String> users = new ArrayList<String>();
		com.google.gdata.client.appsforyourdomain.UserService guserService = new com.google.gdata.client.appsforyourdomain.UserService(
				"ykko-test");

		String consumerKey = appProperties.getConsumerKey();
		String consumerSecret = appProperties.getConsumerKeySecret();
		String urlEscopo = "http://apps-apis.google.com/a/feeds/user/#readonly";
		GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
		oauthParameters.setOAuthConsumerKey(consumerKey);
		oauthParameters.setOAuthConsumerSecret(consumerSecret);
		oauthParameters.setOAuthType(OAuthType.TWO_LEGGED_OAUTH);

		oauthParameters.setScope(urlEscopo);

		try {
			guserService.setOAuthCredentials(oauthParameters,
					new OAuthHmacSha1Signer());
			guserService.setReadTimeout(20000);
			guserService.setConnectTimeout(20000);
			final String APPS_FEEDS_URL_BASE = "https://apps-apis.google.com/a/feeds/";
			final String SERVICE_VERSION = "2.0";

			String domainUrlBase = APPS_FEEDS_URL_BASE + domain + "/";

			URL retrieveUrl = new URL(domainUrlBase + "user/" + SERVICE_VERSION);
			UserFeed genericFeed = new UserFeed();

			Link nextLink = null;

			do {
				try {
					UserFeed newGenericFeed = guserService.getFeed(retrieveUrl,
							UserFeed.class);

					genericFeed.getEntries()
							.addAll(newGenericFeed.getEntries());
					nextLink = newGenericFeed.getLink(Link.Rel.NEXT,
							Link.Type.ATOM);
					if (nextLink != null) {
						retrieveUrl = new URL(nextLink.getHref());
					}
				} catch (AppsForYourDomainException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (ServiceException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} while (nextLink != null);

			if (genericFeed != null && genericFeed.getEntries() != null
					&& !genericFeed.getEntries().isEmpty()) {
				for (UserEntry genericEntry : genericFeed.getEntries()) {
					// System.out.println(genericEntry.getLogin().getUserName());
					domainUsers.add(genericEntry.getLogin().getUserName() + "@"
							+ domain);
				}
			}
		} catch (OAuthException e) {
			e.printStackTrace();

		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return domainUsers;
	}

	private String getDomainAdminUserId(String email) {
		String adminEmail = null;
		// List<String> users = new ArrayList<String>();
		com.google.gdata.client.appsforyourdomain.UserService guserService = new com.google.gdata.client.appsforyourdomain.UserService(
				"ykko-test");

		String consumerKey = appProperties.getConsumerKey();
		String consumerSecret = appProperties.getConsumerKeySecret();
		String urlEscopo = "http://apps-apis.google.com/a/feeds/user/#readonly";
		GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
		oauthParameters.setOAuthConsumerKey(consumerKey);
		oauthParameters.setOAuthConsumerSecret(consumerSecret);
		oauthParameters.setOAuthType(OAuthType.TWO_LEGGED_OAUTH);

		oauthParameters.setScope(urlEscopo);

		try {
			guserService.setOAuthCredentials(oauthParameters,
					new OAuthHmacSha1Signer());
			guserService.setReadTimeout(20000);
			guserService.setConnectTimeout(20000);
			final String APPS_FEEDS_URL_BASE = "https://apps-apis.google.com/a/feeds/";
			final String SERVICE_VERSION = "2.0";

			String domainUrlBase = APPS_FEEDS_URL_BASE
					+ UserUtil.getDomain(email) + "/";

			URL retrieveUrl = new URL(domainUrlBase + "user/" + SERVICE_VERSION);
			UserFeed genericFeed = new UserFeed();

			Link nextLink = null;

			do {
				try {
					UserFeed newGenericFeed = guserService.getFeed(retrieveUrl,
							UserFeed.class);

					genericFeed.getEntries()
							.addAll(newGenericFeed.getEntries());
					nextLink = newGenericFeed.getLink(Link.Rel.NEXT,
							Link.Type.ATOM);
					if (nextLink != null) {
						retrieveUrl = new URL(nextLink.getHref());
					}
				} catch (AppsForYourDomainException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (ServiceException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} while (nextLink != null);

			if (genericFeed != null && genericFeed.getEntries() != null
					&& !genericFeed.getEntries().isEmpty()) {
				for (UserEntry genericEntry : genericFeed.getEntries()) {
					// System.out.println(genericEntry.getLogin().getUserName());
					if (genericEntry.getLogin().getAdmin()) {
						adminEmail = genericEntry.getLogin().getUserName();
						System.out.println("admin email is  : " + adminEmail);
						break;
					}
				}
			}
		} catch (OAuthException e) {
			e.printStackTrace();

		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return adminEmail;
	}

	public List<AppUser> getAllUsers(String createdBy) {
		return appUserDao.getAllUsers(createdBy);
	}

	public List<AppUser> searchUsers(GridRequest dataCriteria, String email) {
		return appUserDao.searchUsers( dataCriteria,  email);
	}

	public void remove(AppUser appUser) {
	appUserDao.remove(appUser);
		
	}

}
